//
//  TextViewController.m
//  iLiteNote
//
//  Created by xiangism on 15/8/26.
//  Copyright (c) 2015年 LiteNice. All rights reserved.
//

#import "TextViewController.h"
#import "AppUtility.h"

extern "C" {
#include "crypt/fileio.h"
}

@interface TextViewController () {
    UITextView *_textView;
    
    NSString *_notePath;    //笔记的完整路径
    NSString *_noteName;    //从路径中去掉父文件夹和拓展名后的名称
    BOOL _textChanged;      //点击save按钮后，文本是否有变化
    BOOL _isCrypt;          //是否加密过
    NSString *_cryptKey;    //crypt的密码
    
    NSMutableArray *_historyText;
    int _historyIndex;
    UIBarButtonItem *_undoItem;
    UIBarButtonItem *_redoItem;
}

@end


@implementation TextViewController

- (id) init:(NSString*)notepath {
    self = [super init];
    if (self) {
        _notePath = notepath;
    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self setNavigate];
    [self setTextView];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboarderWillShow:) name:UIKeyboardWillShowNotification object:nil];
}

- (void)setNavigate {
    UINavigationItem *navItem = self.navigationItem;
    
    //navItem.backBarButtonItem.title = @"返回";
    
    UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeSystem];
    btn1.frame = CGRectMake(0, 0, 100, 30);
    btn1.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
    [btn1 setTitle:@"< 返回" forState:UIControlStateNormal];
    [btn1 addTarget:self action:@selector(backTouch:) forControlEvents:UIControlEventTouchUpInside];
    UIBarButtonItem *itemBack = [[UIBarButtonItem alloc] initWithCustomView:btn1];
    navItem.leftBarButtonItem = itemBack;
    
    UIButton *btn2 = [UIButton buttonWithType:UIButtonTypeSystem];
    btn2.frame = CGRectMake(0, 0, 40, 30);
    btn2.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;
    [btn2 setTitle:@"Save" forState:UIControlStateNormal];
    [btn2 addTarget:self action:@selector(saveTouch:) forControlEvents:UIControlEventTouchUpInside];
    UIBarButtonItem *itemSave = [[UIBarButtonItem alloc] initWithCustomView:btn2];
    navItem.rightBarButtonItem = itemSave;
    
    NSString * name = _notePath.lastPathComponent;
    NSRange r = [name rangeOfString:@"." options:NSBackwardsSearch];
    if (r.length != 0) {
        _noteName = [name substringWithRange:NSMakeRange(0, r.location)];
    } else {
        _noteName = name;
    }
    navItem.title = _noteName;
}

- (void)setTextView {
    
    //int w = ScreenWidth;
    //int h = ScreenHeight;
    //if (w <= 375)
        //f = [UIFont fontWithName:@".SF UI Text" size:18];
        //f = [UIFont systemFontOfSize:18];
    //else 
        //f = [UIFont fontWithName:@".SF UI Text" size:16];
    //f = [UIFont systemFontOfSize:16];
    UIFont * f = [UIFont fontWithName:@"DejaVu Sans Mono" size:16];
    
    _textView = [[UITextView alloc] initWithFrame:self.view.frame];
    _textView.delegate = self;
    _textView.font = f;
    _textView.backgroundColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1];
    _textView.textColor = [UIColor whiteColor];
    [self.view addSubview:_textView];
    
    NSData *textData = [NSData dataWithContentsOfFile:_notePath];
    
    if ([AppUtility isCryptFileWithData:textData]) {
        const char *filename = [_notePath cStringUsingEncoding:NSUTF8StringEncoding];
        char *str = read_crypt_file(filename, [self.cryptKey cStringUsingEncoding:NSUTF8StringEncoding]);
        NSString *ns = [[NSString alloc] initWithUTF8String:str];
        if (!ns) {
            ns = [NSString stringWithFormat:@"%s", str];
            _textView.textColor = [UIColor yellowColor];
            _textView.editable = NO;
            UINavigationItem *navItem = self.navigationItem;
            navItem.title = [NSString stringWithFormat:@"%@(密码错误, 文本不可编译)", _noteName];
            navItem.rightBarButtonItem = nil;
        }
        free(str);
        _textView.text = ns;
        _isCrypt = YES;
        
        _historyText = [NSMutableArray arrayWithObject:[NSString stringWithFormat:@"%@", ns]];
        _historyIndex = 0;
        
    } else {
        NSString *str = [[NSString alloc]initWithData:textData encoding:NSUTF8StringEncoding];
        _textView.text = str;
        _isCrypt = NO;
        
        _historyText = [NSMutableArray arrayWithObject:str];
        _historyIndex = 0;
    } 
    _textChanged = NO;
    
    int width = 40;
    CGRect accessoryFrame = CGRectMake(0.0, 0.0, self.view.bounds.size.width, width);
    UIToolbar *inputAccessoryView = [[UIToolbar alloc] initWithFrame:accessoryFrame];
    inputAccessoryView.translucent = YES;
    inputAccessoryView.backgroundColor = [UIColor whiteColor];
    
    static const int size = 6;
    // # * . , 在搜狗键盘上就自定义出来
    // 这里只所有没有用NSArray的二维数组，是因为SEL是c的原生指针放到NSArray中很麻烦
    SEL sel[size] = {@selector(insertChar3), @selector(insertChar6), @selector(insertChar7), @selector(insertChar8), @selector(undo), @selector(redo)};
    NSArray *titles = [NSArray arrayWithObjects:@"```", @"+", @"-", @"tab", @"Undo", @"Redo", nil];
    NSMutableArray *items = [[NSMutableArray alloc] init];
    
    for (int i = 0; i < size; ++i) {
        UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithTitle:titles[i] style:UIBarButtonItemStylePlain target:self action:sel[i]];
        item.width = width;
        
        [items addObject:item];
    }
    _undoItem = items[items.count-2];
    _redoItem = items[items.count-1];
    [_undoItem setEnabled:NO];
    [_redoItem setEnabled:NO];
    
    [inputAccessoryView setItems:items];
    _textView.inputAccessoryView = inputAccessoryView;
    _textView.layoutManager.allowsNonContiguousLayout = NO;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

- (void)viewWillDisappear:(BOOL) animated {
    
}

- (void)alterSave {
    if (_textChanged) {
        
        UIAlertController *ctrl = [UIAlertController alertControllerWithTitle:@"文本已修改, 是否保存?" message:@"" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *cancelAct = [UIAlertAction actionWithTitle:@"不保存, 直接退出" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
            [self.navigationController popViewControllerAnimated:YES];
        }];
        UIAlertAction *okAct = [UIAlertAction actionWithTitle:@"保存" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            [self saveFile];
            [self.navigationController popViewControllerAnimated:YES];
        }];
        
        [ctrl addAction:cancelAct];
        [ctrl addAction:okAct];
        [self presentViewController:ctrl animated:YES completion:nil];
    }
    [self.navigationController popViewControllerAnimated:YES];
}

#pragma mark - Action

- (void)saveFile {
    if (_textChanged) {
        if (_isCrypt) {
            const char *filename = [_notePath cStringUsingEncoding:NSUTF8StringEncoding];
            const char *str = [_textView.text cStringUsingEncoding:NSUTF8StringEncoding];
            write_crypt_file(filename, str, [_cryptKey cStringUsingEncoding:NSUTF8StringEncoding]);
            
        } else {
            NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingUTF8);
            NSData *data = [_textView.text dataUsingEncoding:enc];
            [data writeToFile:_notePath atomically:NO];
        }
        if (self.refreshBlock) {
            self.refreshBlock();
        }
        _textChanged = NO;
    }
}

- (IBAction)backTouch:(id)sender {
    [self.view endEditing:YES];
    [self alterSave];
}

- (IBAction)saveTouch:(id)sender {
    [self.view endEditing:YES];
    [self saveFile];
    self.navigationItem.title = _noteName;
}

- (IBAction)canelTouch:(id)sender {
    [self.navigationController popViewControllerAnimated:YES];
}

- (void)insertChar:(NSString*)ch {
    [self insertChar:ch withLen:[ch length]];
}

- (void)insertChar:(NSString*)ch withLen:(NSInteger)len {
    NSRange selRange = _textView.selectedRange;
    NSString *old_str = _textView.text;
    BOOL is_end = old_str.length == selRange.location;
    NSString *new_str = [NSString stringWithFormat:@"%@%@%@", [old_str substringToIndex:selRange.location], ch, [old_str substringFromIndex:selRange.location]];
    [_textView setText:new_str];
    selRange.location += len;
    _textView.selectedRange = selRange;
    selRange.location -= len;
    selRange.location += [ch length]*2; //将插入的所有文本都显示出来
    
    [_textView scrollRangeToVisible:selRange];
    
    if ([ch compare:@"```\n\n```"] == NSOrderedSame && is_end) {
        CGPoint p = _textView.contentOffset;
        _textView.contentOffset = CGPointMake(p.x, p.y+20);
    }
}

- (BOOL)insertChar1 {
    [self insertChar:@"#"];
    return YES;
}
- (BOOL)insertChar2 {
    [self insertChar:@"*"];
    return YES;
}
- (BOOL)insertChar3 {
    [self insertChar:@"```\n\n```" withLen:4];
    return YES;
}
- (BOOL)insertChar4 {
    [self insertChar:@","];
    return YES;
}
- (BOOL)insertChar5 {
    [self insertChar:@"." ];
    return YES;
}
- (BOOL)insertChar6 {
    [self insertChar:@"+"];
    return YES;
}
- (BOOL)insertChar7 {
    [self insertChar:@"-"];
    return YES;
}
- (BOOL)insertChar8 {
    [self insertChar:@"    "];
    return YES;
}

- (BOOL)undo {
    if (_historyText.count > 1 && _historyIndex >= 0) {
        if (_historyIndex > 0) {
            --_historyIndex;
        }
        NSRange selRange = _textView.selectedRange;
        
        _textView.text = _historyText[_historyIndex];
        
        _textView.selectedRange = NSMakeRange(selRange.location, 0);
        [self setTextChanged];
        [self setUnRedoState];
    }
    return YES;
}

- (BOOL)redo {
    if (_historyText.count > 1 && _historyIndex <= _historyText.count-1) {
        ++_historyIndex;
        NSRange selRange = _textView.selectedRange;
        
        _textView.text = _historyText[_historyIndex];
        
        _textView.selectedRange = NSMakeRange(selRange.location, 0);
        [self setTextChanged];
        [self setUnRedoState];
    }
    return YES;
}

- (void)setUnRedoState {
    if (_historyIndex > 0) {
        [_undoItem setEnabled:YES];
    } else {
        [_undoItem setEnabled:NO];
    }
    if (_historyIndex < _historyText.count-1) {
        [_redoItem setEnabled:YES];
    } else {
        [_redoItem setEnabled:NO];
    }
}

- (void)setTextChanged {
    UINavigationItem *navItem = self.navigationItem;
    navItem.title = [NSString stringWithFormat:@"%@ *", _noteName];
    _textChanged = true;
}

#pragma mark - UITextView delegate

- (void)keyboarderWillShow:(NSNotification*)notification {
    NSDictionary *userInfo = [notification userInfo];
    NSValue *value = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
    CGRect keyRect = [value CGRectValue];
    _textView.frame = CGRectMake(0, 0,self.view.frame.size.width, self.view.frame.size.height-keyRect.size.height);
    
}

- (void)textViewDidBeginEditing:(UITextView *)textView {
}

- (void)textViewDidEndEditing:(UITextView *)textView {
    _textView.frame = self.view.frame;
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    [textField resignFirstResponder];
    return YES;
}

- (void)textViewDidChange:(UITextView *)textView {
    [self setTextChanged];
    
    if (_historyIndex < _historyText.count-1) {
        [_historyText removeObjectsInRange:NSMakeRange(_historyIndex+1, _historyText.count-1-_historyIndex)];
        
    }
    [_historyText addObject:_textView.text];
    _historyIndex = (int)_historyText.count-1;
    [self setUnRedoState];
}

@end

